# 220131 1948

# 数据结构

# 列表可以修改，而字符串和元组不能

# 列表
# list.
# append, extend, insert, remove, pop, clear, index,
# count, sort, reverse, copy
# copy-浅复制

a = [1,2,3,4,5,5,6,7,3,2]
print('original a:')
print(a)

ret = a.reverse()
print('after reversed: ret=', ret) # None
print(a)

# 只删除第一个
ret = a.remove(3)
print('after removing 3: ret=', ret) # None
print(a)

# 删除不存在的，异常
#a.remove(999) # ValueError: list.remove(x): x not in list
#print('after removing 999:')
#print(a)

# 类似 insert, remove 或 sort 等修改列表的方法没有返回值

print('end.1')

# 将列表当做堆栈使用
# 最先进入的元素最后一个被释放（后进先出）
# append, pop

# index=0的元素为 栈底
stack = [3,4,5]
print('stack 1: ', stack)

stack.append(6)
print('stack 2: ', stack)

stack.append(7)
print('stack 3: ', stack)

ret = stack.pop();
print('stack 4: ', stack, ', ret=', ret)

ret = stack.pop();
print('stack 5: ', stack, ', ret=', ret)

ret = stack.pop();
print('stack 5: ', stack, ', ret=', ret)

ret = stack.pop();
print('stack 5: ', stack, ', ret=', ret)

ret = stack.pop();
print('stack 5: ', stack, ', ret=', ret)

# ret = stack.pop(); # IndexError: pop from empty list
#print('stack 5: ', stack, ', ret=', ret)

print('end.2')

# 将列表当作队列使用
# 拿列表用作这样的目的效率不高！
# （因为所有其他的元素都得一个一个地移动）

# 使用 deque

from collections import deque

# index=0的元素为 队首——先出
queue = deque(["Eric", "John", "Michael"])
print('queue 1:', queue)
queue.append('Terry')
queue.append('Graham')
print('queue 2:', queue)

ret = queue.popleft();
print('queue 3:', queue, ', ret=', ret)

print('end.3')

# 列表推导式
# 从序列创建列表的简单途径
# 每个列表推导式都在 for 之后跟一个表达式，然后有零到多个 for 或 if 子句。
# 返回结果是一个根据表达从其后的 for 和 if 上下文环境中生成出来的列表。
# 如果希望表达式推导出一个元组，就必须使用括号。

vec = [2,4,6]
print('vec=', vec)

newvec = [3*x for x in vec]
print('newvec=', newvec)

vecmap = [[x, x**2] for x in vec]
print('vecmap=', vecmap)

# 对序列里每一个元素逐个调用某方法
freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
print('freshfruit=', freshfruit)

# 清理前后空格
stripFreshfruit = [weapon.strip() for weapon in freshfruit]
print('stripFreshfruit=', stripFreshfruit)

# 用 if 子句作为过滤器
print('if 过滤：', [3*x for x in vec if x > 3])

# 关于循环和其它技巧
vec1 = [2, 4, 6]
vec2 = [4, 3, -9]

# 3X3=9
print([x*y for x in vec1 for y in vec2]) # [8, 6, -18, 16, 12, -36, 24, 18, -54]

# 1X1X3=3
print([vec1[i]*vec2[i] for i in range(len(vec1))]) # [8, 12, -54]

# 使用复杂表达式或嵌套函数
print([str(round(355/113, i)) for i in range(1,6)]) # ['3.1', '3.14', '3.142', '3.1416', '3.14159']

print('end.4')

# 嵌套列表解析

matrix = [
	[1,2,3,4],
	[5,6,7,8],
	[9,10,11,12]
]
print('matrix=', matrix)

# 将3X4的矩阵列表转换为4X3列表
matrix140 = [[row[i] for row in matrix] for i in range(4)]
print('matrix140=', matrix140) # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

# 方法2
transposed = []
for i in range(4):
	transposed.append([row[i] for row in matrix])
print('transposed=', transposed)

# 方法3
transposed3 = []
for i in range(4):
	transposed_now = []
	for row in matrix:
		transposed_now.append(row[i])
	transposed3.append(transposed_now)
print('transposed3=', transposed3)

print('end.5')

# del 语句
# 根据索引来删除一个元素
# 与使用 pop() 返回一个值不同
# 可以用 del 语句从列表中删除一个切割(slice)
# 或清空整个列表

dela = [-1, 1, 66.25, 333, 333, 1234.5]
print('dela 1=', dela)

del dela[0]
print('dela 2=', dela)

del dela[2:4]
print('dela 3=', dela)

del dela[:]
print('dela 4=', dela)

print('end.6')

# 元组和序列
t181 = 12345, 54321, 'hello!'
print(t181)
print(type(t181)) # <class 'tuple'>

t185 = t181, (1,2,3,4,5)
print(t185)
print(type(t185)) # <class 'tuple'>

# 元组在输出时总是有括号的

print('end.7')

# 集合
# set
# 集合是一个无序不重复元素的集。
# 基本功能包括关系测试和消除重复元素
# 可以用大括号({})创建集合
# 创建一个空集合，你必须用 set() 而不是 {} 

basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print('basket=', basket)

print('orange' in basket) # True
print('crabgrass' in basket) # False

print()

# 字符串转集合
sa = set('abracadabra')
sb = set('alacazam')
print('sa=', sa) # {'b', 'c', 'r', 'a', 'd'}
print('sb=', sb) # {'c', 'z', 'l', 'a', 'm'}

print('操作：')
print('-: ', sa-sb)
print('|: ', sa|sb)
print('&: ', sa&sb)
print('^: ', sa^sb)

# 推导式
a221 = {x for x in 'abracadabra' if x not in 'abc'}
print('a221=', a221) # {'d', 'r'}

print('end.8')

# 字典 220202 914
# 一对大括号创建一个空的字典：{}
# 关键字可以是任意不可变类型，通常用字符串或数值

tel = {'jack':2222, 'spae':1111}
print('tel=', tel)
print('tel.keys=', tel.keys()) # dict_keys(['jack', 'spae'])

print(tel['jack'])
#print(tel['jackno']) # KeyError: 'jackno'

del tel['spae'] # 删除
print('删除后 tel=', tel)

tel['tom']=3333
print('添加后 tel=', tel)

print('list: ', list(tel.keys()))
print('sorted: ', sorted(tel.keys()))

print('test1: ', 'a' in tel)
print('test2: ', 'jack' in tel)

# 构造函数 dict() 直接从键值对元组列表中构建字典。
# 如果有固定的模式，列表推导式指定特定的键值对

dict252 = dict([('a', 97),('b', 98),('c', 99)])
print('dict252=', dict252)

dict255 = {x:x**2 for x in (2,4,6)}
print('dict255=', dict255)

# 如果关键字只是简单的字符串，使用关键字参数指定键值对有时候更方便

dict260 = dict(sp=3333, dt=2222, cad=9999)
print('dict260=', dict260)

print('end.9')

# 遍历技巧

# 字典 items() 方法
weekDays={1:'Monday', 2:'Tuesday', 3:'Wednesday', 4:"Thursday",
5:'Friday', 6:'Saturday', 7:'Sunday'}
for k,v in weekDays.items():
	print(k, v)

# 序列 enumerate() 方法
for i,v in enumerate(['tic', 'tac', 'toe']):
	print(i, v)

# 同时遍历两个或更多的序列 zip() 方法
strs=['a','b','c','d']
nums=[1,2,3,4,5,6,7]
for str,num in zip(strs, nums):
	# 没有 5、6、7 输出
	print('str={0}, num={1}'.format(str,num))

# 反向遍历序列 reversed() 方法
for i in reversed(range(1,10,2)):
	print('i=', i)

# 遍历 加 sorted() 方法
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
	print('f=', f)

print('end.10')
